/*
 * sleep.c
 *
 *  Created on: 2017年5月12日
 *      Author: chenss
 */


#include <io/watchdog.h>
#include "sleep.h"
#include "message_queue.h"

#include <string.h>

// 每次休眠时间（秒），必须小于60秒
#define SLEEP_INTERVAL 20

static void _GoToSleep(void);

void Sleep_Init(void)
{
    RTC_InitTypeDef  RTC_InitStructure;
    RTC_TimeTypeDef  RTC_TimeStruct;

    /* Enable the PWR clock */
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    /* Allow access to RTC */
    PWR_BackupAccessCmd(ENABLE);

    /* Reset RTC Domain */
    RCC_BackupResetCmd(ENABLE);
    RCC_BackupResetCmd(DISABLE);

    /* Enable the LSE OSC */
    RCC_LSEConfig(RCC_LSE_ON);
//    RCC_LSICmd(ENABLE);

    /* Wait till LSE is ready */
    while(RCC_GetFlagStatus(RCC_FLAG_LSERDY) == RESET)
    {}

    /* Select the RTC Clock Source */
    RCC_RTCCLKConfig(RCC_RTCCLKSource_LSE);

    /* Configure the RTC data register and RTC prescaler */
    /* ck_spre(1Hz) = RTCCLK(LSI) /(AsynchPrediv + 1)*(SynchPrediv + 1)*/
    RTC_InitStructure.RTC_AsynchPrediv = 0x7F;
    RTC_InitStructure.RTC_SynchPrediv  = 0xFF;
    RTC_InitStructure.RTC_HourFormat   = RTC_HourFormat_24;
    RTC_Init(&RTC_InitStructure);

    /* Set the time to 00h 00mn 00s AM */
    RTC_TimeStructInit(& RTC_TimeStruct);
    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);

    EXTI_InitTypeDef EXTI_InitStructure;
    RTC_AlarmTypeDef RTC_AlarmStructure;
    NVIC_InitTypeDef NVIC_InitStructure;

    /* EXTI configuration */
    EXTI_ClearITPendingBit(EXTI_Line17);
    EXTI_InitStructure.EXTI_Line = EXTI_Line17;
    EXTI_InitStructure.EXTI_Mode = EXTI_Mode_Interrupt;
    EXTI_InitStructure.EXTI_Trigger = EXTI_Trigger_Rising;
    EXTI_InitStructure.EXTI_LineCmd = ENABLE;
    EXTI_Init(&EXTI_InitStructure);

    /* Enable the RTC Alarm Interrupt */
    NVIC_InitStructure.NVIC_IRQChannel = RTC_IRQn;
    NVIC_InitStructure.NVIC_IRQChannelPriority = 2;
    NVIC_InitStructure.NVIC_IRQChannelCmd = ENABLE;
    NVIC_Init(&NVIC_InitStructure);

    RTC_AlarmStructInit(&RTC_AlarmStructure);
    RTC_AlarmStructure.RTC_AlarmMask = RTC_AlarmMask_Minutes;
    RTC_AlarmStructure.RTC_AlarmTime.RTC_Seconds = SLEEP_INTERVAL;
    RTC_SetAlarm(RTC_Format_BIN, RTC_Alarm_A, &RTC_AlarmStructure);

    /* Wait for RTC APB registers synchronisation */
    RTC_WaitForSynchro();


    RTC_ClearITPendingBit(RTC_IT_ALRA);
    EXTI_ClearITPendingBit(EXTI_Line17);
    RTC_ITConfig(RTC_IT_ALRA, ENABLE);


    /* Enable the RTC Clock */
    RCC_RTCCLKCmd(ENABLE);

    _GoToSleep();
}

static void _GoToSleep(void)
{
    RTC_TimeTypeDef  RTC_TimeStruct;

    RTC_TimeStructInit(& RTC_TimeStruct);
    RTC_SetTime(RTC_Format_BIN, &RTC_TimeStruct);
    RTC_WaitForSynchro();
    RTC_AlarmCmd(RTC_Alarm_A, ENABLE);

//    PWR_EnterSTOPMode(PWR_Regulator_LowPower, PWR_STOPEntry_WFI);
}

void Sleep_IdleAfter(int msIdleAfter)
{
    _GoToSleep();
}

void RTC_IRQHandler(void)
{
    int value;

  /* Check on the AlarmA flag and on the number of interrupts per Second (60*8) */
  if(RTC_GetITStatus(RTC_IT_ALRA) != RESET)
  {
      /* Clear RTC AlarmA Flags */
      RTC_ClearITPendingBit(RTC_IT_ALRA);
      RTC_AlarmCmd(RTC_Alarm_A, DISABLE);

//      const char *str = "Alarm\r\n";
//      MsgQueue_Send(MsgQueue_Id_IntPrint, str, strlen(str));

      value = WatchDog_Get();
      if(value < (2 * 60))
      {
          WatchDog_Feed();
      }

      WatchDog_Set(value + SLEEP_INTERVAL);

      MsgQueue_Send(MsgQueue_Id_Monitor, NULL, 0);
      Sleep_IdleAfter(2000);
  }
  /* Clear the EXTIL line 17 */
  EXTI_ClearITPendingBit(EXTI_Line17);

}

